import { Material, Mesh, MeshBasicMaterial, MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial, Object3D } from 'three';
import { Command } from '../command.js';
import { Editor } from '../editor.js';

/**
 * @param editor Editor
 * @param object THREE.Object3D
 * @param attributeName string
 * @param newValue number, string, boolean or object
 * @constructor
 */
class SetMaterialValueCommand<M extends Material|MeshBasicMaterial|MeshStandardMaterial|MeshPhongMaterial|MeshLambertMaterial|MeshLambertMaterial,K extends keyof M> extends Command {

	object:Mesh;
	material:M;
	oldValue:any;
	newValue:any;
	attributeName:K;
	constructor( editor:Editor, object:Object3D, attributeName:K, newValue:any, materialSlot:number ) {

		super( editor );

		this.type = 'SetMaterialValueCommand';
		this.name = `Set Material.${attributeName.toString()}`;
		this.updatable = true;

		this.object = object as Mesh;
		this.material = this.editor.getObjectMaterial( this.object, materialSlot ) as M;

		this.oldValue = ( this.material !== undefined ) ? this.material[ attributeName ] : undefined;
		this.newValue = newValue;

		this.attributeName = attributeName;

	}

	execute() {

		this.material[ this.attributeName ] = this.newValue;
		this.material.needsUpdate = true;

		this.editor.signals.objectChanged.dispatch( this.object );
		this.editor.signals.materialChanged.dispatch( this.material );

	}

	undo() {

		this.material[ this.attributeName ] = this.oldValue;
		this.material.needsUpdate = true;

		this.editor.signals.objectChanged.dispatch( this.object );
		this.editor.signals.materialChanged.dispatch( this.material );

	}

	update( cmd:SetMaterialValueCommand<M,K> ) {

		this.newValue = cmd.newValue;

	}

	

}

export { SetMaterialValueCommand };
